<script setup lang='ts' name="admin-role">
import type { VxeGridProps, VxePagerEvents } from 'vxe-table'
import { useSessionStorage } from '@vueuse/core'
import type { FormInstance } from 'element-plus'
import { SearchForm, SearchTable } from '@fl/components'
import { cloneDeep } from 'lodash-es'
import type { IForm, IState } from './types'
import { dialogTitle } from './types'
import { addRole, deleteRole, editRole, getCardDetailById, getCardList, getCompanyByLoginUser, getCompanyCard, getRoleById, getRoleList, getUserMenus, roleBindMenu } from '@fl/api/joint-api'
import { useTree } from './hooks/useTree'
import AuthUserDialog from './authUser.vue'
import { useJointStore } from '@fl/store/modules/joint'
import { useUserStore } from '@fl/store/modules/user'

const jointCard = useJointStore().getJointCardInfo
console.log('🚀 ~ jointAppKey:', jointCard)
const userStore = useUserStore()
const isManager = ref<boolean>(userStore.getUserInfo?.userFlag === '2')

const initialState: IState = {
    appKey: jointCard.appKey,
    appId: Number(jointCard.appId),
    name: '',
}
const active = ref(0)
const cardList = ref<{ name: string, appId: number, appKey: string }[]>([])
// const plate = ref()
const state = ref({ ...initialState })
const statusList = [{
    label: '正常',
    value: 0,
}, {
    label: '禁用',
    value: 1,
}]
const isEdit = ref(false)
const companyId = ref('')
const startIdx = ref(0)
const columns = ref([
    {
        label: '角色名称',
        prop: 'name',
        valueType: 'copy',
    },
    {
        label: '所属应用',
        prop: 'appKey',
        options: undefined,
        valueType: 'select',
    },
])
const isLoading = ref(false)
const initialPage = {
    currentPage: 1,
    pageSize: 10,
    total: 0,
}
const tablePage = ref(cloneDeep(initialPage))
const gridOptions = reactive<VxeGridProps>({
    columns: [
        // { field: 'id', minWidth: 90, title: '序号' },
        { title: '序号', type: 'seq', width: 50 },
        { field: 'name', minWidth: 90, title: '角色名称' },
        // { field: 'roleKey', minWidth: 80, title: '负责区域' },
        { field: 'appName', minWidth: 80, title: '所属应用' },
        { field: 'status', minWidth: 100, slots: { default: 'status' }, title: '状态' },
        { field: 'creator', title: '创建人', width: 120 },
        { field: 'createTime', title: '创建时间', width: 200 },
        { fixed: 'right', minWidth: 120, slots: { default: 'operate' }, title: '操作' },
    ],
})
const list = ref([])
const initForm: IForm = {
    menuCheckStrictly: true,
    menuIds: [],
    remark: '',
    code: undefined,
    appKey: jointCard.appKey,
    appId: jointCard.appId,
    name: undefined,
    sort: 0,
    disabled: 0,
    type: 1,
}
const selectRef = ref()
const formRef = ref()
const form = ref(cloneDeep(initForm))
const rules = {
    appKey: [
        { message: '所属应用不能为空', required: true, trigger: 'blur' },
    ],
    code: [
        { message: '角色编码不能为空', required: true, trigger: 'blur' },
    ],
    name: [
        { message: '角色名称不能为空', required: true, trigger: 'blur' },
    ],
    status: [
        { message: '状态不能为空', required: true, trigger: 'change' },
    ],
}
const title = ref('新增角色')
const visible = ref(false)
const menuOptions = ref([])
const menuProps = ref({
    children: 'children',
    label: 'label',
    value: 'id',
})
const currentRoleId = ref('')
const menuExpand = ref(false)
const menuNodeAll = ref(false)
const menuTreeRef = ref()
const roleIds = ref('')

const { isPending, mutateAsync: runAddRole } = useMutation({
    mutationFn: (data: any) => addRole(data),
    onSuccess: async (data) => {
        if (data) {
            ElMessage.success('保存成功')
            currentRoleId.value = data
            active.value++
        }
        else {
            ElMessage.error('保存失败')
        }
    },
})

async function getRoleMenu() {
    const menuTreeData = await getRoleById({ id: currentRoleId.value })
    console.log('🚀 ~ showDialog ~ menuTreeData:', menuTreeData)
    if (menuTreeData?.appMenus?.length) {
        // menuOptions.value = menuTreeData.menus
        const checkedList = menuTreeData.appMenus.map(v => v.id)
        console.log('🚀 ~ showDialog ~ checkedList:', checkedList)

        form.value.menuIds = checkedList

        nextTick(() => {
            checkedList.forEach((v) => {
                menuTreeRef.value.setChecked(v, true, false)
            })
        })
    }
}

const { isPending: updatePending, mutateAsync: runUpdateRole } = useMutation({
    mutationFn: (data: any) => editRole(data),
    onSuccess: async (data) => {
        if (data) {
            ElMessage.success('保存成功')
            active.value++
        }
        else {
            ElMessage.error('保存失败')
        }
    },
})

async function getMenuList(appKey) {
    const appMenus = await getUserMenus({ appKey })
    // console.log('🚀 ~ getCardMenus ~ res:', appMenus)
    if (appMenus?.length) {
        const { treeData } = useTree(appMenus)
        console.log('🚀 ~ getCardMenus ~ treeData:', treeData)

        menuOptions.value = treeData
        menuProps.value = {
            children: 'children',
            label: 'name',
            value: 'id',
        }
    }
}

function next() {
    formRef.value.validate(async (valid) => {
        if (valid) {
            const { appKey, name, code, disabled } = form.value
            console.log('🚀 ~ formRef.value.validate ~ form.value:', form.value)
            if (isEdit.value) {
                await runUpdateRole({ id: currentRoleId.value, name, code, disabled, appKey, sort: 1, type: 1, ext1: companyId.value })
                await getMenuList(appKey)
                await getRoleMenu()
                menuExpand.value = true
                handleCheckedTreeExpand(true)
            }
            else {
                await runAddRole({ name, code, disabled, appKey, sort: 1, type: 1, ext1: companyId.value })
                getMenuList(appKey)
            }
        }
    })
}

async function getListData() {
    companyId.value = window.sessionStorage.getItem('companyId') || ''
    if (!companyId.value) {
        const companyDetail = await getCompanyByLoginUser()
        companyId.value = companyDetail.id
        useSessionStorage('companyId', companyDetail.id)
        useSessionStorage('companyDetail', companyDetail)
    }

    const res = await getCompanyCard()
    cardList.value = [{ name: jointCard.appName, appKey: jointCard.appKey, appId: Number(jointCard.appId) }, ...res.map(card => ({ name: card.cardName, appKey: card.appKey, appId: Number(card.cardId) }))] || []

    columns.value.forEach((item) => {
        if (item.prop === 'appKey') {
            item.options = cardList.value.map(card => ({
                label: card.name,
                value: card.appKey,
                appId: card.appId,
            }))
        }
    })

    getRoleList({
        ...state.value,
        pageNo: tablePage.value.currentPage,
        pageSize: tablePage.value.pageSize,
    }).then((res) => {
        list.value = res.list
        tablePage.value.total = res.total
    })
}

getListData()

function setStatus(row) {
    const { roleId, status } = row
    console.log('🚀 ~ setStatus ~ row:', row)

    // roleStatus({
    //     roleId,
    //     status,
    // }).then((res) => {
    //     console.log(2333, res)
    //     ElMessage.success('操作成功')
    //     getListData()
    // }).catch(() => {
    //     getListData()
    // })
}

const handlePageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }) => {
    tablePage.value.currentPage = currentPage
    tablePage.value.pageSize = pageSize
    startIdx.value = (currentPage - 1) * pageSize
    getListData()
}

function resetSearch() {
    state.value = cloneDeep(initialState)
    getListData()
}

function submitSearch(values) {
    console.log('🚀 ~ submitSearch ~ values:', values)

    if (values) {
        const { appKey, name } = values

        state.value = {
            name,
            appKey,
        }

        tablePage.value.currentPage = 1
        getListData()
    }
}

function changeApp(value) {
    console.log('🚀 ~ changeApp ~ value:', value)
    // 通过ref获取到选中的节点
    // const selectedItem = cardList.value.find(item => item.appId === value)
    // if (!selectedItem)
    //     return
    // console.log('🚀 ~ changeApp ~ selectedItem:', selectedItem)
    // form.value.appKey = selectedItem.appKey
}

// 树权限（展开/折叠）
function handleCheckedTreeExpand(value) {
    for (let i = 0; i < menuOptions.value.length; i++) {
        menuTreeRef.value.store.nodesMap[menuOptions.value[i].id as number].expanded = value
    }
}

// 树权限（全选/全不选）
function handleCheckedTreeNodeAll(value) {
    menuTreeRef.value.setCheckedNodes(value ? menuOptions.value : [])
}
// 树权限（父子联动）
function handleCheckedTreeConnect(value) {
    form.value.menuCheckStrictly = !!value
}

// 所有菜单节点数据
function getMenuAllCheckedKeys() {
    // 目前被选中的菜单节点
    const checkedKeys = menuTreeRef.value.getCheckedKeys()
    // 半选中的菜单节点
    const halfCheckedKeys = menuTreeRef.value.getHalfCheckedKeys()
    checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
    return checkedKeys
}

// 打开弹窗
async function showDialog(type, row) {
    menuNodeAll.value = false
    title.value = type
    const { appKey, appId, code, name, roleSort, disabled } = row
    console.log('🚀 ~ showDialog ~ row:', row, cardList.value)

    switch (type) {
        case dialogTitle.ADD:
            form.value = cloneDeep(initForm)
            visible.value = true
            isEdit.value = false
            break
        case dialogTitle.EDIT:
            currentRoleId.value = row.id
            // 后台返回的appKey有问题，通过前端appId去匹配准确的appKey
            const currentApp = cardList.value.find(item => item.appId === appId)
            console.log('🚀 ~ showDialog ~ currentApp:', currentApp)
            form.value = {
                menuCheckStrictly: true,
                menuIds: [],
                appKey: currentApp?.appKey,
                appId: currentApp?.appId,
                code,
                name,
                roleSort,
                disabled: Number(disabled),
            }
            isEdit.value = true
            visible.value = true
            break
    }
}

// 取消按钮
function cancel() {
    visible.value = false
    active.value = 0
    getListData()
}
function reset() {
    formRef.value.resetFields()
    visible.value = false
    active.value = 0
}

// 提交按钮
function submitForm(formEl: FormInstance | undefined) {
    if (!formEl)
        return
    formEl.validate((valid) => {
        if (valid) {
            const params = {
                appMenuIds: undefined,
                id: currentRoleId.value,
            }
            switch (title.value) {
                case dialogTitle.ADD:
                    params.appMenuIds = getMenuAllCheckedKeys()
                    console.log('🚀 ~ formEl.validate ~ params:', params)
                    roleBindMenu(params).then(() => {
                        reset()

                        getListData()
                        ElMessage.success('新增成功')
                    })
                    break
                case dialogTitle.EDIT:
                    params.appMenuIds = getMenuAllCheckedKeys()
                    roleBindMenu(params).then(() => {
                        reset()

                        getListData()
                        ElMessage.success('修改成功')
                    })
                    break
            }
            visible.value = false
        }
    })
}

function delRole(row) {
    ElMessageBox.confirm(
        row?.id ? `您确定要删除角色『${row.name}』吗？` : '您确定要所勾选的角色吗？',
        row?.id ? '删除' : '批量删除',
        {
            cancelButtonText: '取消',
            confirmButtonText: '删除',
            type: 'warning',
        },
    )
        .then(() => {
            const params = row?.id ?? roleIds.value
            deleteRole({ id: params }).then(() => {
                ElMessage.success('删除成功')
                getListData()
            }).catch(() => {
                ElMessage.error('接口请求失败')
            })
        }).catch(() => {
            ElMessage({
                message: '取消删除',
                type: 'info',
            })
        })
}

function checkboxChange(values) {
    const ids = values.records.map(item => item.roleId)
    roleIds.value = ids.join()
}

const authUserVisible = ref(false)
function toAuth(row) {
    authUserVisible.value = true
}

/**
 * methods end
*/
</script>

<template>
    <div class="sys-role">
        <ElCard class="mb-20" shadow="never">
            <SearchForm v-model="state" :columns="columns" submit-text="搜索" @reset="resetSearch"
                @submit="submitSearch" />
        </ElCard>

        <ElCard shadow="never">
            <SearchTable v-bind="gridOptions" v-model:pager="tablePage" :loading="isLoading" :data="list"
                :seq-config="{ startIndex: startIdx }" @page-change="handlePageChange"
                @checkbox-change="checkboxChange">
                <template #toolbar_buttons>
                    <el-button v-if="isManager" plain type="primary" @click="showDialog(dialogTitle.ADD, {})">
                        新增
                    </el-button>
                </template>

                <template #time="{ row }">
                    {{ row.startTime }} ~ {{ row.endTime }}
                </template>

                <template #status="{ row }">
                    <!-- <el-switch v-model="row.status"
                               active-value="0"
                               inactive-value="1"
                               @change="setStatus(row)"
                    /> -->
                    {{ row.disabled ? '禁用' : '正常' }}
                </template>

                <template #operate="{ row }">
                    <!-- roleId为1是超级管理员 -->
                    <div v-if="row.roleId !== 1" class="operate-btns">
                        <el-button type="primary" text @click="showDialog(dialogTitle.EDIT, row)">
                            编辑
                        </el-button>

                        <!-- <el-button type="primary"
                                   text
                                   @click="toAuth(row)"
                        >
                            分配用户
                        </el-button> -->

                        <el-button type="default" text @click="delRole(row)">
                            删除
                        </el-button>
                    </div>
                </template>
            </SearchTable>
        </ElCard>
        <!-- 添加或修改角色配置对话框 -->
        <el-dialog v-model="visible" :title="title" width="666px">
            <el-form ref="formRef" class="dialog-form" :model="form" :rules="rules" label-width="100px"
                label-position="right">
                <el-steps style="max-width: 600px" :active="active" align-center finish-status="success">
                    <el-step title="创建角色" />

                    <el-step title="绑定菜单" />
                </el-steps>

                <div v-if="active === 0" class="mt-20">
                    <el-form-item label="所属应用" prop="appKey">
                        <el-select ref="selectRef" v-model="form.appKey" :disabled="isEdit" placeholder="请选择所属应用"
                            @change="changeApp">
                            <el-option v-for="item in cardList" :key="item.appKey" :label="item.name"
                                :value="item.appKey" />
                        </el-select>
                    </el-form-item>

                    <el-form-item label="角色名称" prop="name">
                        <el-input v-model="form.name" placeholder="请输入角色名称" />
                    </el-form-item>

                    <el-form-item label="角色编码" prop="code">
                        <el-input v-model="form.code" :disabled="isEdit" placeholder="请输入角色编码" />
                    </el-form-item>

                    <el-form-item label="状态">
                        <el-radio-group v-model="form.disabled">
                            <el-radio v-for="dict in statusList" :key="dict.value" :value="dict.value">
                                {{ dict.label }}
                            </el-radio>
                        </el-radio-group>
                    </el-form-item>
                </div>

                <div v-else>
                    <el-form-item label="菜单权限">
                        <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand">
                            展开/折叠
                        </el-checkbox>

                        <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll">
                            全选/全不选
                        </el-checkbox>

                        <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect">
                            父子联动
                        </el-checkbox>
                    </el-form-item>

                    <el-form-item label="">
                        <el-tree ref="menuTreeRef" class="tree-border w-500" :data="menuOptions" show-checkbox
                            node-key="id" :check-strictly="!form.menuCheckStrictly" :props="menuProps" />
                    </el-form-item>
                </div>
            </el-form>

            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="cancel">
                        取 消
                    </el-button>

                    <el-button v-if="active === 0" :loading="isPending || updatePending" @click="next">
                        {{ isEdit ? '下一步' : ' 创建角色' }}
                    </el-button>

                    <el-button v-else type="primary" @click="submitForm(formRef)">
                        确 定
                    </el-button>
                </div>
            </template>
        </el-dialog>

        <AuthUserDialog v-if="authUserVisible" v-model="authUserVisible" :role-id="currentRoleId"
            @close="authUserVisible = false" />
    </div>
</template>

<style lang="scss" scoped>
.sys-role {
    .dialog-form {
        height: calc(100vh - 400px);
        overflow-y: auto;
    }

    .dialog-footer {
        display: flex;
        justify-content: end;
        margin-top: 30px;
    }

    :deep(.operate-btns .el-button) {
        margin: 0;
        padding: 6px;
    }
}
</style>
